﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using Cofe.Core;
using Cofe.Core.Implements;
using Cofe.Core.Interfaces;
using Cofe.Core.Logger;
using Cofe.Web.Utils;
using Cofe.Core.Property;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Cofe.Web.Feed
{
    /// <summary>
    /// CofeEventArgsFeedService.
    /// </summary>
    #region EventArgsFeedService

    [Export(typeof(ICofeService))]
    [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFEWS)]
    public class CofeSystemEventArgsFeedService : FeedServiceBase<CofeSystemEventArgs>
    {
        public CofeSystemEventArgsFeedService()
            : base()
        {
            string appLogPath = 
                HttpRuntime.AppDomainAppId == null ? 
                PathFE.Combine(PathFE.GetDirectoryName(
                System.Reflection.Assembly.GetExecutingAssembly().Location), "log") :
                PathFE.Combine(HttpRuntime.AppDomainAppPath, "log");

            this.FileSystem = new FeedFileSystemHelper(
                PathFE.Combine(appLogPath, "current"),
                PathFE.Combine(appLogPath, "archive"),
                PathFE.Combine(appLogPath, "entry"));
                
            this.Builder = new CofeSystemEventArgsFeedBuilder(this)
            {
                FeedTemplate = new UriTemplate("/api/events?page={id}"),
                EventTemplate = new UriTemplate("/api/events/{id}"),
                EntryTemplate = new UriTemplate("/api/entry/{id}")
            };

            this.Links.IncludeBaseAddress = false;
            //Repository/Links/Updater are set in base class.
        }
    }

    #endregion

    #region EventArgsFeedBuilder

    public class CofeSystemEventArgsFeedBuilder : FeedBuilderBase<CofeSystemEventArgs>
    {
        #region Constructor


        public CofeSystemEventArgsFeedBuilder(IFeedService<CofeSystemEventArgs> feedService)
            : base(feedService)
        {
            ServiceName = "CofeSystemEventArgsFeedBuilder";
            Title = "CofeSystemInfo Events";
        }

        #endregion

        #region Methods


        private void buildSyndicationItem(IEventLog<CofeSystemEventArgs> eventLog, out SyndicationItem retVal, out Guid eventLogId)
        {
            eventLogId = Guid.NewGuid(); 
            var type = eventLog.EventArgs.ChangeType.ToString().ToLower();
            var entryType = eventLog.EventArgs.IsFolder ? "folder" : "file";
            var title = string.Format("{0} {1} is {2} ", entryType, eventLog.EventArgs.FullParsePath, type);

            using (var v = CofeServices.SecurityManager.ImpersonateAsService("VolumeRegistrar"))
            {

                CofeSystemInfo entry = 
                    eventLog.EventArgs.ChangeType == ModifiedAction.Deleted ? null : 
                    EntryFE.TryParsePathAsync(eventLog.EventArgs.FullParsePath, ParsableType.ParsePath).Result as CofeSystemInfo;
                var entryId = entry != null && entry.Properties.Behaviors.IsPropertySupported(CacheProperties.Id) ?
                    entry.Properties.Behaviors.GetProperty<Guid>(CacheProperties.Id) : Guid.Empty;
   

                retVal = new SyndicationItem()
                {
                    Id = string.Format("tag:entry,{0}:{1}", eventLog.UtcTime.ToString("yyyy-MM-dd"), eventLogId),
                    Title = new TextSyndicationContent(title),
                    LastUpdatedTime = eventLog.UtcTime.ToLocalTime()
                };

                retVal.Authors.Add(new SyndicationPerson(eventLog.UserId));
                retVal.Categories.Add(new SyndicationCategory("type/" + type));
                retVal.Categories.Add(new SyndicationCategory("entry/" + entryType));
                retVal.Links.Add(_feedService.Links.CreateEventLink(LinkType.self, eventLog, eventLogId));


                
                var jObject = entry != null ?
                    CofeServices.EntrySerializer.WriteEntry(entry, false, false) :
                    new JObject(new JProperty("path", eventLog.EventArgs.FullParsePath));
                if (eventLog.EventArgs is CofeRenameEventArgs)
                    jObject.Add(new JProperty("oldPath", 
                        (eventLog.EventArgs as CofeRenameEventArgs).OldParsePath));

                retVal.Content = SyndicationContent.CreatePlaintextContent(jObject.ToString());


                //StringBuilder sb = new StringBuilder();
                //Func<string> getMask = () => sb.Length == 0 ? "{0}={1}" : "&{0}={1}";
                //if (entry != null)
                //{
                //    foreach (var p in entry.Properties.SupportedDefinitions.GetSupportedProperties())
                //        if (CofeServices.PropertyDictionary.AttributeHelper.IsWebMetadata(p))
                //        {
                //            sb.Append(string.Format(getMask(),
                //                CofeServices.PropertyDictionary.GetPropertyString(p).ToLower(),
                //                entry.Properties.Behaviors.GetProperty(p).Value));
                //        }
                //}
                //else sb.Append(string.Format(getMask(), "path", eventLog.EventArgs.FullParsePath));

                //if (eventLog.EventArgs is CofeRenameEventArgs)
                //    sb.Append(string.Format(getMask(), "oldPath", 
                //        (eventLog.EventArgs as CofeRenameEventArgs).OldParsePath));

                //retVal.Content = SyndicationContent.CreatePlaintextContent(sb.ToString());

                //    var jObject = CofeServices.EntrySerializer.WriteEntry(entry, false, false);
                //    var xmlDocument = JsonConvert.DeserializeXmlNode(jObject.ToString(), "Entry");
                //    using (MemoryStream ms = new MemoryStream())
                //    {
                //        xmlDocument.Save(ms); ms.Seek(0, SeekOrigin.Begin);
                //        var r = XmlReader.Create(ms);
                //        retVal.Content = new XmlSyndicationContent(r);
                //    }
                //    //new UrlSyndicationContent(UrlUtils.FormatUri(entryUrl), "application/xml");
                //}

                if (entryId != Guid.Empty)
                    retVal.Links.Add(
                         _feedService.Links.CreateEntryLink(LinkType.related, entryId));
                
            }
        }


        public override FeedEntry<CofeSystemEventArgs> BuildEntry(IEventLog<CofeSystemEventArgs> eventLog)
        {            
            SyndicationItem syndItem; 
            Guid eventLogId;
            buildSyndicationItem(eventLog, out syndItem, out eventLogId);
            //item.Links.Add(_feedService.Links.CreateEntryLink(LinkType.self, eventLog, eventLogId));
            //item.Links.Add(_feedService.Links.CreateEntryLink(LinkType.via, eventLog, eventLogId));
            //item.Content = new XmlSyndicationContent("application/xml", evnt.Body.Payload, null as DataContractSerializer);

            return new FeedEntry<CofeSystemEventArgs>(syndItem, eventLogId + ".atom");
        }

        #endregion

        #region Data

        #endregion

        #region Public Properies



        #endregion

    }

    #endregion



}
